package com.atguigu.tingshu.search.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.aggregations.Buckets;
import co.elastic.clients.elasticsearch._types.aggregations.LongTermsBucket;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.CompletionSuggestOption;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.json.JsonData;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.AlbumInfoIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.alibaba.nacos.common.utils.CollectionUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {

    private final  static  String INDEX_NAME ="albuminfo";
    //建议词词库
    private static final String SUCCEST_INDEX_NAME = "suggestinfo";

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private AlbumFeignClient albumFeignClient;

    @Autowired
    private AlbumInfoIndexRepository albumInfoIndexRepository;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 站内检索，支持关键字、分类、标签条件分页检索，结果高亮
     * @param albumIndexQuery 查询条件对象：包含关键字、分类id、标签列表、排序、分页信息
     * @return
     */
    @Override
    @SneakyThrows
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {
       //1.解析DSL语句
        //SearchRequest searchRequest=  this.builderDSL(albumIndexQuery);
        SearchRequest searchRequest=  this.builkkkkkldDSL(albumIndexQuery);
        System.err.println("本次检索DSL：复制到Kibana中验证");
        System.err.println(searchRequest.toString());

        //2.调用原生ES客户端对象进行检索
        SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);

        //3.封装结果响应前端
        AlbumSearchResponseVo albumSearchResponseVo=  this.parseResult(searchResponse,albumIndexQuery);
        return  albumSearchResponseVo;

    }


    /**
     * 查询1级分类下置顶3级分类下包含分类热门专辑
     * @param category1Id 一级分类
     * @return
     */
    @Override
    @SneakyThrows
    public List<Map<String, Object>> getTopCategory3HotAlbumList(Long category1Id) {

        //1.先获取全部的三级分类信息
        List<BaseCategory3> baseCategory3List = albumFeignClient.getTop7BaseCategory3(category1Id).getData();
        Assert.notNull(baseCategory3List,"查询三级分类信息降级 ：" +category1Id );

        //获取分类的id
        List<Long> baseCategory3IdList = baseCategory3List.stream().map(baseCategory3 -> baseCategory3.getId()).collect(Collectors.toList());

        Map<Long, BaseCategory3> category3Map = baseCategory3List.stream()
                .collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));


        List<FieldValue> fieldValueList = baseCategory3IdList.stream()
                .map(baseCategory3Id -> FieldValue.of(baseCategory3Id))
                .collect(Collectors.toList());


        //2.解析DSL语句
        SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(
                s -> s.index(INDEX_NAME).size(0)
                        .query(q -> q.terms(t -> t.field("category3Id").terms(tf -> tf.value(fieldValueList))))
                        .aggregations("category3Agg", a -> a.terms(t -> t.field("category3Id").size(10))
                                .aggregations("top6Agg", a1 -> a1.topHits(t -> t.size(6).sort(so -> so.field(f ->
                                        f.field("hotScore").order(SortOrder.Desc))))))

                , AlbumInfoIndex.class);

        //解析结果
        Aggregate category3IdAgg = searchResponse.aggregations().get("category3Agg");
        //因为是三级分类ID字段类型为Long 调用Iterms 获取桶
        Buckets<LongTermsBucket> buckets = category3IdAgg.lterms().buckets();
        List<LongTermsBucket> bucketList = buckets.array();
        if(CollectionUtils.isNotEmpty(bucketList)){
            List<Map<String, Object>> mapList = bucketList.stream().map(bucket -> {
                HashMap<String, Object> hashMap = new HashMap<>();
                //处理热门专辑——》分类
                long cateory3Id = bucket.key();
                BaseCategory3 baseCategory3 = category3Map.get(cateory3Id);
                hashMap.put("baseCategory3", baseCategory3);

                //处理热门专辑
                Aggregate top6Agg = bucket.aggregations().get("top6Agg");
                List<Hit<JsonData>> hits = top6Agg.topHits().hits().hits();
                //一个个的对象
                if (CollectionUtils.isNotEmpty(hits)) {
                    List<AlbumInfoIndex> albumInfoIndexList = hits.stream().map(hit -> {
                        //获取JSON对象
                        JsonData source = hit.source();
                        AlbumInfoIndex to = source.to(AlbumInfoIndex.class);
                        return to;
                    }).collect(Collectors.toList());

                    hashMap.put("list", albumInfoIndexList);
                }

                return hashMap;

            }).collect(Collectors.toList());

            return mapList;


        }
        return null;
    }

    /**
     * 封装结果响应前端
     * @param searchRequest
     * @return
     */
    private AlbumSearchResponseVo parseResult(SearchResponse<AlbumInfoIndex> searchResponse, AlbumIndexQuery queryVo) {

        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        albumSearchResponseVo.setPageNo(queryVo.getPageNo());
        albumSearchResponseVo.setPageSize(queryVo.getPageSize());

        //1.1 从ES响应结果中得到总记录数
        long total = searchResponse.hits().total().value();

        long totalPages = total % queryVo.getPageSize() == 0 ? total / queryVo.getPageSize() : total / queryVo.getPageSize() + 1;
        albumSearchResponseVo.setTotalPages(totalPages);
        albumSearchResponseVo.setTotal(total);


        //封装检索出来的商品信息
        List<Hit<AlbumInfoIndex>> hits = searchResponse.hits().hits();
        if(CollectionUtils.isNotEmpty(hits)){
            List<AlbumInfoIndexVo> albumInfoIndexVos = hits.stream().map(hit -> {
                AlbumInfoIndexVo albumInfoIndexVo = BeanUtil.copyProperties(hit.source(), AlbumInfoIndexVo.class);

                //处理高亮片段
                Map<String, List<String>> highlight = hit.highlight();
                if (CollectionUtil.isNotEmpty(highlight) && highlight.containsKey("albumTitle")) {
                    String highlightAlbumTitle = highlight.get("albumTitle").get(0);
                    albumInfoIndexVo.setAlbumTitle(highlightAlbumTitle);

                }

                return albumInfoIndexVo;

            }).collect(Collectors.toList());
            //添加集合
            albumSearchResponseVo.setList(albumInfoIndexVos);

        }



        return albumSearchResponseVo;
    }

    /**
     * 解析DSL语句
     * @param albumIndexQuery
     * @return
     */
    private SearchRequest builkkkkkldDSL(AlbumIndexQuery querVo) {
        //1.创建索引构造器对象--封转检索索引库
        SearchRequest.Builder searchRequest = new SearchRequest.Builder();
        searchRequest.index(INDEX_NAME);

        //2.设置请求体参数"query"，处理查询文件
        BoolQuery.Builder builder = new BoolQuery.Builder();
        //获取关键字
        String keyword = querVo.getKeyword();
        if(StringUtils.isNotBlank(keyword)){
            //2.2.1设置匹配查询专辑标题
            builder.should(s->s.match(m-> m.field("albumTitle").query(keyword)));

            builder.should(s->s.match(m->m.field("albumIntro").query(keyword)));
            builder.should(s->s.term(m->m.field("announcerName").value(keyword)));

        }

        //2.3三级分类
        if(querVo.getCategory1Id()!=null){
            builder.filter(f-> f.term(t->t.field("category1Id").value(querVo.getCategory1Id())));
        }
        if(querVo.getCategory2Id()!=null){
            builder.filter(f-> f.term(t->t.field("category2Id").value(querVo.getCategory2Id())));
        }
        if(querVo.getCategory3Id()!=null){
            builder.filter(f-> f.term(t->t.field("category3Id").value(querVo.getCategory3Id())));
        }

        // //2.4 处理标签查询条件(可能有多个)
        List<String> attributeList = querVo.getAttributeList();
        if(!CollectionUtils.isEmpty(attributeList)){
            for (String attribute : attributeList) {
                String[] split = attribute.split(":");
                if(split!= null && split.length==2){



                    //创建多条件查询对象
                    BoolQuery.Builder attributeBoolQuery = new BoolQuery.Builder();
                attributeBoolQuery.filter(f -> f.term(t -> t.field("attributeValueIndexList.attributeId").value(split[0])));
                attributeBoolQuery.filter(f -> f.term(t -> t.field("attributeValueIndexList.valueId").value(split[1])));


                builder.filter(f -> f.nested(n ->

                        n.path("attributeValueIndexList")
                                .query(attributeBoolQuery.build()._toQuery())));
                }
            }
        }

        //2.5将里层的builer放到外层（2——》1）
        searchRequest.query(builder.build()._toQuery());

        //3处理分页
        int pageSize = (querVo.getPageNo() - 1) * (querVo.getPageSize());
        searchRequest.from(pageSize).size(querVo.getPageSize());

        //4.排序
        //4.1 判断参数排序是否提交 提交形式： 排序字段（1：综合 2：播放量 3：发布时间）:排序方式
        String order = querVo.getOrder();
        if(StringUtils.isNotBlank(order)){
            String[] split = order.split(":");
            if(split!=null && split.length==2){
                String orderFieId ="";
                switch (split[0]){
                    case "1":
                        orderFieId ="hotScore";
                        break;
                    case "2":
                        orderFieId ="playStatNum";
                        break;
                    case "3":
                        orderFieId ="createTime";
                        break;
                }

                //4.2排序到build 设置排序
                String finalOrderField = orderFieId;
                searchRequest.sort(s->s.field(f->f.field(finalOrderField).order("asc".equals(split[1]) ? SortOrder.Asc:SortOrder.Desc)));
            }
        }

        //5设置高亮
        if (StringUtils.isNotBlank(keyword)) {
            searchRequest.highlight(h->h.fields("albumTitle",f->f.preTags("<font style='color:red'>").postTags("</font>")));
        }


        //6.排除字段
        searchRequest.source(s->s.filter(f->f.excludes("category1Id",
                "category2Id",
                "category3Id"
           )));

        return searchRequest.build();

    }

    public SearchRequest builderDSL(AlbumIndexQuery query) {


        //创建请求对象
        SearchRequest.Builder builder = new SearchRequest.Builder();

        //设置索引库
        builder.index(INDEX_NAME);

        //创建封装所有条件的多条件对象
        BoolQuery.Builder allBoolQuery = new BoolQuery.Builder();

        //获取关键字
        String keyword = query.getKeyword();
        //判断
        if (StringUtils.isNotEmpty(keyword)) {
            //专辑标题
            allBoolQuery.should(s -> s.match(m -> m.field("albumTitle").query(keyword)));
            allBoolQuery.should(s -> s.match(m -> m.field("albumIntro").query(keyword)));
            allBoolQuery.should(s -> s.term(t -> t.field("announcerName").value(keyword)));

        }


        //封装三级分类条件

        //判断
        if (query.getCategory1Id() != null && query.getCategory1Id() != 0) {

            allBoolQuery.filter(f -> f.term(t -> t.field("category1Id").value(query.getCategory1Id())));


        }

        if (query.getCategory2Id() != null && query.getCategory2Id() != 0) {

            allBoolQuery.filter(f -> f.term(t -> t.field("category2Id").value(query.getCategory2Id())));


        }
        if (query.getCategory3Id() != null && query.getCategory3Id() != 0) {

            allBoolQuery.filter(f -> f.term(t -> t.field("category3Id").value(query.getCategory3Id())));
        }


        //处理专辑属性过滤器

        //获取专辑属性条件
        List<String> attributeList = query.getAttributeList();
        //判断
        if (CollectionUtils.isNotEmpty(attributeList)) {

            //遍历属性集合
            for (String attribute : attributeList) {
                //attribute == 属性id:属性值id
                //获取属性id和属性值ID
                String[] split = attribute.split(":");
                //判断
                if (split != null && split.length == 2) {


                    //创建多条件查询对象
                    BoolQuery.Builder attributeBoolQuery = new BoolQuery.Builder();
                    attributeBoolQuery.filter(f -> f.term(t -> t.field("attributeValueIndexList.attributeId").value(split[0])));
                    attributeBoolQuery.filter(f -> f.term(t -> t.field("attributeValueIndexList.valueId").value(split[1])));


                    allBoolQuery.filter(f -> f.nested(n ->
                            n.path("attributeValueIndexList")
                                    .query(attributeBoolQuery.build()._toQuery())));

                }


            }


        }


        //设置查询条件query
        builder.query(allBoolQuery.build()._toQuery());


//        //设置分页数据
        builder.size(query.getPageSize());
        //开始的索引
        //开始的索引=（当前页-1）*每页条数
        int startIndex = (query.getPageNo() - 1) * query.getPageSize();
        builder.from(startIndex);
//
//        //设置高亮
        //前提：必须是keyword关键检索，才能确定高亮的内容
        if (StringUtils.isNotEmpty(keyword)) {
            builder.highlight(h -> h.fields("albumTitle", hi -> hi.preTags("<font color='red'>").postTags("</font>")));
        }
//
//        //设置排序
        //排序（综合排序[1:desc] 播放量[2:desc] 发布时间[3:desc]；asc:升序 desc:降序）
        String order = query.getOrder();
        //判断
        if (StringUtils.isNotEmpty(order)) {

            //判断
            String[] split = order.split(":");
            //定义字段
            String field = "";
            //根据排序字段条件的参数转化
            switch (split[0]) {
                case "1":
                    field = "hotScore";
                    break;
                case "2":
                    field = "playStatNum";
                    break;
                case "3":
                    field = "createTime";
                    break;

            }

            String finalField = field;

            builder.sort(s -> s.field(f -> f.field(finalField).order(split[1].equals("desc") ? SortOrder.Desc : SortOrder.Asc)));

        }


//
//
//        //设置返回过滤字段
        builder.source(s -> s.filter(fi -> fi.excludes("category1Id",
                "category2Id",
                "category3Id",
                "attributeValueIndexList.attributeId",
                "attributeValueIndexList.valueId")));

        return builder.build();
    }

    /**
     * 上架专辑-导入索引库
     * @param albumId 专辑id
     */
    @Override
    public void upperAlbum(Long albumId) {
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //1.专辑的基本信息
            AlbumInfo albumInfo = albumFeignClient.getAlbumInfo(albumId).getData();
            Assert.notNull(albumInfo, "专辑不存在 ：：专辑id{}", albumId);
            albumInfoIndex.setId(albumId);
            albumInfoIndex.setAlbumTitle(albumInfo.getAlbumTitle());
            albumInfoIndex.setAlbumIntro(albumInfo.getAlbumIntro());
            albumInfoIndex.setCoverUrl(albumInfo.getCoverUrl());
            albumInfoIndex.setIncludeTrackCount(albumInfo.getIncludeTrackCount());
            albumInfoIndex.setIsFinished(albumInfoIndex.getIsFinished());
            albumInfoIndex.setPayType(albumInfo.getPayType());
            albumInfoIndex.setCreateTime(new Date());



            return albumInfo;
        }, threadPoolExecutor);


        CompletableFuture<Void> voidCompletableFuture1 = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            //2.专辑的属性值
            List<AlbumAttributeValue> albumAttributeValueVoList = albumInfo.getAlbumAttributeValueVoList();
            if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
                //专辑属性不为空
                List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueVoList.stream().map(albumAttributeValue -> {
                    AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                    attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                    attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                    return attributeValueIndex;
                }).collect(Collectors.toList());
                albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
            }
        });


        CompletableFuture<Void> voidCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync((albumInfo) -> {
            //3.三级分类
            BaseCategoryView baseCategoryView = albumFeignClient.getCategoryView(albumInfo.getCategory3Id()).getData();
            Assert.notNull(baseCategoryView, "查询三级分类降级了 ：三级分类:{}", albumInfo.getCategory3Id());
            albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
            albumInfoIndex.setCategory3Id(baseCategoryView.getCategory3Id());
        }, threadPoolExecutor);


        CompletableFuture<Void> voidCompletableFuture3 = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            //4.用户名字
            UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(albumInfo.getUserId()).getData();
            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
        }, threadPoolExecutor);


        CompletableFuture<Void> voidCompletableFuture2 = CompletableFuture.runAsync(() -> {
            //5.专辑的播放量 ....四个属性
            int playStatNum = RandomUtil.randomInt(1000, 2000);
            int subscribeStatNum = RandomUtil.randomInt(500, 1000);
            int buyStaNum = RandomUtil.randomInt(200, 400);
            int commentStatNum = RandomUtil.randomInt(100, 200);
            albumInfoIndex.setPlayStatNum(playStatNum);
            albumInfoIndex.setSubscribeStatNum(subscribeStatNum);
            albumInfoIndex.setCommentStatNum(commentStatNum);
            albumInfoIndex.setBuyStatNum(buyStaNum);

            //6.商品的热度
            BigDecimal bigDecimal1 = new BigDecimal(playStatNum).multiply(new BigDecimal("0.4"));
            BigDecimal bigDecimal2 = new BigDecimal(subscribeStatNum).multiply(new BigDecimal("0.3"));
            BigDecimal bigDecimal3 = new BigDecimal(buyStaNum).multiply(new BigDecimal("0.2"));
            BigDecimal bigDecimal4 = new BigDecimal(commentStatNum).multiply(new BigDecimal("0.1"));
            BigDecimal hotScore = bigDecimal1.add(bigDecimal2).add(bigDecimal3).add(bigDecimal4);
            albumInfoIndex.setHotScore(hotScore.doubleValue());
        }, threadPoolExecutor);

        //线程的排序
        CompletableFuture.allOf(
                albumInfoCompletableFuture,
                voidCompletableFuture1,
                voidCompletableFuture2,
                voidCompletableFuture,
                voidCompletableFuture3).join();


        //将专辑信息放到索引库
        albumInfoIndexRepository.save(albumInfoIndex);
    }


    /**
     * 下架专辑-删除文档
     * @param albumId 专辑id
     */
    @Override
    public void lowerAlbum(Long albumId) {
        albumInfoIndexRepository.deleteById(albumId);
    }


    /**
     * 根据用户录入部分关键字进行自动补全
     *
     * @param keyword
     * @return
     */
    @Override
    public List<String> completeSuggest(String keyword) {
        try {
            //1.根据用户录入关键字进行建议提词请求发起
            SearchResponse<SuggestIndex> searchResponse = elasticsearchClient.search(
                    s -> s.index(SUCCEST_INDEX_NAME)
                            .suggest(s1 -> s1.suggesters("mySuggestKeyword", fs -> fs.prefix(keyword).completion(c -> c.field("keyword").size(10).skipDuplicates(true)))
                                    .suggesters("mySuggestPinyin", fs -> fs.prefix(keyword).completion(c -> c.field("keywordPinyin").size(10).skipDuplicates(true)))
                                    .suggesters("mySuggestSequence", fs -> fs.prefix(keyword).completion(c -> c.field("keywordSequence").size(10).skipDuplicates(true)))
                            )
                    , SuggestIndex.class
            );
            //2.解析建议词响应结果，将结果进行去重
            Set<String> hashSet = new HashSet<>();
            hashSet.addAll(this.parseSuggestResult("mySuggestKeyword", searchResponse));
            hashSet.addAll(this.parseSuggestResult("mySuggestPinyin", searchResponse));
            hashSet.addAll(this.parseSuggestResult("mySuggestSequence", searchResponse));
            if (hashSet.size() >= 10) {
                return new ArrayList<>(hashSet).subList(0, 10);
            }
            //3.如果建议词记录数小于10，采用全文查询专辑索引库尝试补全
            SearchResponse<AlbumInfoIndex> response = elasticsearchClient.search(
                    s -> s.index(INDEX_NAME).query(q -> q.match(m -> m.field("albumTitle").query(keyword))),
                    AlbumInfoIndex.class

            );
            //解析检索结果，将结果放入HashSet
            List<Hit<AlbumInfoIndex>> hits = response.hits().hits();
            if (CollectionUtil.isNotEmpty(hits)) {
                for (Hit<AlbumInfoIndex> hit : hits) {
                    AlbumInfoIndex albumInfoIndex = hit.source();
                    hashSet.add(albumInfoIndex.getAlbumTitle());
                    if (hashSet.size() >= 10) {
                        break;
                    }
                }
            }
            //4.最多返回10个自动补全提示词
            return new ArrayList<>(hashSet);
        } catch (Exception e) {
            log.error("[搜索服务]建议词自动补全异常：{}", e);
            throw new RuntimeException(e);
        }
    }


    /**
     * 解析建议词结果
     *
     * @param suggestName    自定义建议名称
     * @param searchResponse ES响应结果对象
     * @return
     */
    @Override
    public Collection<String> parseSuggestResult(String suggestName, SearchResponse<SuggestIndex> searchResponse) {
        //1.获取指定自定义建议词名称获取建议结果
        List<Suggestion<SuggestIndex>> suggestionList = searchResponse.suggest().get(suggestName);
        //2.获取建议自动补全对象
        List<String> list = new ArrayList<>();
        suggestionList.forEach(suggestIndexSuggestion -> {
            //3.获取options中自动补全结果
            for (CompletionSuggestOption<SuggestIndex> suggestOption : suggestIndexSuggestion.completion().options()) {
                SuggestIndex suggestIndex = suggestOption.source();
                list.add(suggestIndex.getTitle());
            }
        });
        return list;
    }


    /**
     * 更新所有分类下排行榜-手动调用
     */
    @Override
    @SneakyThrows
    public void updateLatelyAlbumRanking() {
        try {
            //1.先获取所有的一级分类
            List<BaseCategory1> baseCategory1List = albumFeignClient.getAllCategory1().getData();
            Assert.notNull(baseCategory1List,"远程调用获取所有的一级分类失败");
            //2.获取一级分类id
            List<Long> baseCategory1IDList = baseCategory1List.stream().map(baseCategory1 -> baseCategory1.getId()).collect(Collectors.toList());

            //在处理当前1级分类中，再次循环5种不同排序方式得到具体榜单数据
            //3.声明排序方式数组
            String[] arr =
                    new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            for (Long category1Id : baseCategory1IDList) {
                for (String s1 : arr) {
                    //解析DSL语句
                    SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(
                            s -> s.index(INDEX_NAME)
                                    .query(q -> q.term(t -> t.field("category1Id").value(category1Id)))
                                    .sort(sort -> sort.field(f -> f.field(s1).order(SortOrder.Desc)))
                                    .size(10)
                            ,
                            AlbumInfoIndex.class
                    );


                    //封装结果
                    List<Hit<AlbumInfoIndex>> hits = searchResponse.hits().hits();
                    List<AlbumInfoIndex> list = hits.stream().map(hit -> hit.source()).collect(Collectors.toList());
                    //获取到结果的集合
                    //存到redis中
                    String key = RedisConstant.RANKING_KEY_PREFIX + category1Id;
                    redisTemplate.opsForHash().put(key,s1,list);
                }


            }
        } catch (Exception e) {
            log.error("[搜索服务]更新排行榜异常：{}", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取排行榜
     * @param category1Id 一级分类
     * @param dimension 热度 播放量等
     * @return
     */
    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String dimension) {
        String key = RedisConstant.RANKING_KEY_PREFIX + category1Id;
        List<AlbumInfoIndex> albumInfoIndexList = (List)redisTemplate.opsForHash().get(key, dimension);
        if(CollectionUtils.isNotEmpty(albumInfoIndexList)){
            return albumInfoIndexList;
        }
        return null;
    }
}
